六年安卓开发的技术回顾和展望
The following article is from 拭心又在思考了我的天 Author 拭心
今天给朋友们分享的是我们编程导航知识星球新入驻的大厂安卓嘉宾 - 拭心大佬的干货文章。看到最后,相信大家能对软件开发有进一步的认识,帮助自己规划未来。
以下是大佬原文:
大家好,我是 shixin。
一转眼,我从事安卓开发工作已经六年有余,对安卓开发甚至软件开发的价值,每年都有更进一步的认识。对未来的方向,也从刚入行的迷茫到现在逐渐清晰。我想是时候做一个回顾和展望了。
这篇文章会先回顾我从入行至今的一些关键点,然后讲一下经过这些年,我对软件开发的认知变化,最后分享一下后面的规划。
回顾
人太容易在琐碎生活中迷失,我们总是需要记住自己从哪里来,才能清楚要到哪里去。
入行至今的一些关键节点
2014~2015:开始安卓开发之旅
说起为什么做安卓开发,我很有感慨,差一点就“误入歧途”😄。
当初在大学时,加入了西电金山俱乐部,俱乐部里有很多方向:后端、前端、安卓、Windows Phone 等。
由于我当时使用的是三星 i917,WindowsPhone,所以就选了 WinPhone 方向。
当时还是 iOS、安卓、WinPhone、塞班四足鼎立的时代,WinPhone 的磁贴式设计我非常喜欢,加上设备的流畅性、像素高,一度让我觉得它可能会统治移动市场。
结果在学习不到 2 个月以后,我的 WinPhone 意外进水了!我当时非常难过,一方面是对手机坏了的伤痛,另一方面也是对无法继续做 WinPhone 开发很遗憾。对于当时的我来说,再换一台 WinPhone 过于昂贵,只好换一台更加便宜的安卓机,因此也就转向学习安卓开发。
后面的故事大家都知道了,因为 WindowsPhone 缺乏良好的开发生态,支持应用很少,所以用户也少,用户少导致开发者更少,恶性循环,如今市场份额已经少的可怜。
现在回想起来,对于这件事还很有感慨,有些事当时觉得是坏事,拉长时间线去看,未必是这样。
当时还有一件目前看来非常重要的决定:开始写博客,记录自己的所学所得。
在开发项目时,我经常需要去网上搜索解决方案,后来搜索的多了,觉得总不能一直都是索取,我也可以尝试去写一下。于是在 CSDN 注册了账号,并于 2014 年 10 月发布了我的第一篇原创文章。
后来工作学习里新学到什么知识,我都会尽可能地把它转换成别人看得懂的方式,写到播客里。这个不起眼的开始,让我逐渐有了解决问题后及时沉淀、分享的习惯,受益匪浅。
2015~2017:明白项目迭代的全流程
在学习安卓开发时,我先看了一本明日科技的《Android 从入门到精通》,然后看了些校内网的视频,逐渐可以做一些简单的应用。安卓开发所见即所得的特点,让我很快就可以得到正反馈。后来又去参加一些地方性的比赛,获得一些名次,让我逐渐加强了从事这个行业的信心。
在 2015 年时,偶然参加了一家公司的招聘会,在面试时,面试官问了一些简单的 Java 、安卓和算法问题。其中印象最深的就是会不会使用四大组件和 ListView。在当时移动互联网市场飞速发展时,招聘要求就是这么低。以至于现在很多老安卓回忆起当初,都很有感慨:“当初会个 ListView 就能找工作了,现在都是八股文” 哈哈。
到公司实习后,我感触很多,之前都是自己拍脑袋写一些简单的功能,没有开发规范、发布规范,也没有工程结构设计、系统设计,更没有考虑性能是否有问题。真正的去开发一个商业项目,让我发现自己不足的太多了。
因此在完成工作的同时,我观察并记录了项目迭代的各个流程,同时对自己的技术点做查漏补缺,输出了一些 Java 源码分析、Android 进阶、设计模式文章,也是从那个时候开始,养成了定期复盘的习惯,每次我想回顾下过去,都会看看我的成长专栏。
2017~2020:提升复杂项目的架构能力和做事意识
第一个项目中我基本掌握了从 0 到 1 开发一个安卓应用的流程,但对安卓项目架构还只停留在表面,没有足够实践。
在 2017 年,我开始做喜马拉雅直播项目,由于喜马拉雅在当时已经有比较多年的技术积累,加上业务比较复杂,在架构设计、编译加速、快速迭代相关都做了比较多的工作,让我大饱眼福。
同时直播业务本身也是比较复杂的,在一个页面里会集成 IM、推拉流等功能,同时还有大量的消息驱动 UI 刷新操作,要保证业务快速迭代,同时用户体验较好,需要下不少功夫。
为了能够提升自己的技术,在这期间我学习了公司内外很多框架的源码,通过分析这些框架的优缺点、核心机制、架构层级、设计模式,对如何开发一个框架算是有了基本的认识,也输出了一些文章,比如 《Android 进阶之路:深入理解常用框架实现原理》。
有了这些知识,再去做复杂业务需求、基础框架抽取、内部 SDK 和优化,就容易多了。
在开发一些需求或者遇到复杂的问题时,我会先想想,之前看的这些三方框架或者系统源码里有没有类似的问题,它们是怎么解决的?比如开发 PK 功能,这个需求的复杂性在于业务流程很多,分很多状态,咋一看好像很复杂,但如果了解了状态机模式,就会发现很简单。借用其他库的设计思路帮我解决了很多问题,这让我确信了学习优秀框架源码的价值。
除了技术上的提升,在这几年里,我的项目全局思考能力也提升很多。
由于我性格外向,和各个职能的同学沟通交流比较顺畅,领导让我去做一个十人小组的敏捷组长,负责跟进需求的提出、开发、测试、上线、运营各个环节,保证项目及时交付并快速迭代。
一开始我还有些不习惯,写代码时总是被不同的人打断,比如产品需求评审、测试 bug 反馈、运营反馈线上数据有问题等等,经常刚想清楚代码怎么写,正准备动手,就被叫去开会,回来后重新寻找思路。
后来在和领导沟通、看一些书和分享后,逐渐对写代码和做事,有了不同的认识。代码只是中间产物,最终我们还是要拿到对用户有价值、给公司能带来收入的产品,要做到这个,眼里除了代码,还需要关注很多。
2020~至今:深入底层技术
在进入字节做基础技术后,我的眼界再一次被打开。
字节有多款亿级用户的产品,复杂的业务常常会遇到各种意想不到的问题,这些问题需要深入底层,对安卓系统的整个架构都比较熟悉,才能够解决。
上图是安卓系统架构图,之前我始终停留在一二层,在这一时期,终于有了纵深的实践经验。
比如帮业务方解决一个内存问题,除了要了解内存指标监控方式,还要知道分析不同类型内存使用的工具及基本原理,最后知道是哪里出了问题后,还要想如何进行体系化的工具,降低学习成本,提升排查效率。
问题驱动是非常好的学习方式。每次帮助业务解决一个新问题,我的知识库都会多一个点,这让我非常兴奋。之前不知道学来干什么的 Linux 编程、Android 虚拟机,终于在实际问题中明白了使用场景,学起来效率也高了很多。
对软件开发的认识
前面讲了个人的一些经历,包括我怎么入的行,做了什么项目,过程中有什么比较好的实践。下面讲一下我从这些具体的事里面,沉淀出哪些东西有价值的结论。
主要聊下对这两点的认识:
职业发展的不同阶段
技术的价值
职业发展的不同阶段
第一点是对职业发展的认识。我们在工作时,要对自己做的事有一个清晰的认识,它大概属于哪一个阶段,怎样做可以更好。
结合我这些年的工作内容、业内大佬所做的事情,我把软件开发者的职业发展分这几个阶段:
使用某个技术方向的一个点开发简单项目
使用某个技术方向的多个点及某条线,开发一个较为复杂的业务或系统
掌握某个方向的通用知识,有多个线的实践,可以从整体上认识和规划
不限于该方向,能从产品指标方面出发,提供全方位的技术支持业务角度,端到端关注指标
第一个阶段就是使用某个技术方向的一个点完成业务需求。拿安卓开发者来说,比如使用 Android SDK 自定义布局,完成产品要求的界面功能。这个阶段比较简单,只要能够仔细学习官方文档或者看一些书即可胜任。拿后端来说,比如刚接手一个小项目,日常工作就是使用 Spring 等库开发简单的接口,不涉及到上下游通信、数据库优化等。
第二个阶段,你做的项目更加复杂了,会涉及到一个技术方向的多个点,这时你需要能把这些点连起来,给出一个更体系化的解决方案。
拿安卓开发者来说,比如在自定义布局时,发现界面很卡顿,要解决这个问题的话,你就要去了解这个自定义 View 的哪些代码流程影响了这个页面的刷新速度。这就相当于是从一个点到另一个点。怎么连起来呢?你需要去研究渲染的基本原理,分析卡顿的工具,找到导致卡顿的原因,进行优化。这个过程会对流畅性有整体的认识,能够对相关问题有比较全面的分析思路、解决手段,从而可以开发相关的分析工具或优化库。如果能达到这个程度,基本就算是一个高级工程师了,不只是做一个模块,还能够负责一个具体细分方向的工作。
第三个阶段,掌握某个技术方向的通用知识,有多个线的实践,能够连线为面,同时给工作做中长期的技术规划。
拿安卓开发来说,刚才提到你通过解决卡顿问题,在流畅性这方面有了比较多的实践;然后你又发现内存有问题,去了解了内存分配、回收原理,做出内存分析优化工具,这样就也有了内存的一个体系化的实践。再加一些其他的优化经验,比如启动速度、包大小等。把这些线连起来,就得到了一个性能监控平台,这就是有把多条线连成一个面。
还有比如说你发现项目打包和发布过程中的一些痛点,并且能够做一些实践解决,最后如果能够把这些优化项连起来做一个统一的系统,给出完整的 DevOps 方案,提升开发、发布、运维的效率。能够把这个系统搭建起来,有比较深入的经验,那就可以成为“技术专家”了。
再往上走就不只是做技术,而要更多思考业务。技术最终都是要为业务服务。职业发展的第四个阶段,就是不局限于某个技术方向,能够从产品的业务规划、业务指标出发,给产品提供技术支持。
你首先要明白公司业务的核心指标是什么,比如说拿一个短视频应用来说,它核心指标除了常规的日活、用户量,还更关注视频的播放率、停留时长、页面渗透率等。了解这些指标以后,你要思考做什么可以有助于公司提升这些指标。结合业务指标反思当前的项目哪里存在优化空间。
有了这个思路并且知道可以做什么以后,你可以做一个较为全面的规划,然后拉领导去讨论可行性。这时你不能再局限于某一端,不能说我只是个安卓开发,其他部分都找别人做。一般在项目的价值没有得到验证之前,领导不会轻易给你资源,因此第一个版本迭代肯定是要靠你自己,从前到后独立完成,做一个 MVP 版本,然后让领导认可了这个系统的价值,才有可能会分给你更多的资源做这件事。
总结一下对职业发展的认识:第一阶段只做一些具体的点;第二阶段做多个点,需要能够连点成线;第三个阶段需要围绕这些线提炼出通用的知识,然后做到对业务/技术项目有整体的认识;第四阶段能够从业务指标出发,做出有价值的系统/平台。
技术的价值
说完职业发展的不同阶段,接下来聊下技术对业务的价值。
技术是为业务服务的。根据业务的不同阶段,技术的价值也有所不同:
业务从 0 到 1 时,帮助业务快速确定模式
业务从 1 到 100 时,帮助业务快速扩大规模
最卓越的,用技术创新带动业务有新的发展 (Google、AWS、阿里云)
业务从 0 到 1 时
我一开始做的工作,业务就是处于确定模式期间。业务上反复试错,项目常常推倒重来,会让程序员觉得很有挫败感。
这个阶段很多程序员都会发挥复制粘贴大法,产品经理说要新增一个功能,就复制一份代码稍微改一改。
如果说目前就是在这种业务中,该怎么做呢?如果我回到当时那个情景,我可以做什么让公司业务变得更好呢?
我总结了两点:在高效高质量完成业务的同时,思考如何让业务试错成本更低。
如何让业务试错成本更低呢?大概可以有这些方式:
提供可复用的框架
提供便捷的数据反馈机制
多了解一些竞品业务,在产品不确定的时候,给一些建议
第一点:尽可能的抽象相似点,减少重复成本。
如果产品每次都给你类似的需求,你可以考虑如何把这些重复需求抽象成一些可以复用的逻辑,做一个基本的框架,然后在下次开发的时候能够去直接用框架,而不是每次都从头开始。我平时工作也常常问自己“我现在做的事有哪些是重复的,哪些是可以下沉的”。
就安卓开发来说,这个阶段,可以做好基础建设,提供插件化、热修复、动态化框架,帮助业务快速发版,自研还是第三方看公司财力。
如果你说这些太复杂了我做不来,那就从更小的层面做起,比如某个功能原本需要多个接口多个界面,看能不能改成接口参数可配置,界面根据参数动态生成(也就是 DSL)。
第二点:提供便捷的数据反馈机制。
在产品提需求时,你可以问问产品这个需求出于什么考虑,有没有数据支撑?比如说产品需求是某个按钮换个位置,那你要搞清楚,为什么要换,换完之后会导致页面打开率提升吗?要有这种数据驱动的理念。
如果公司做决策时缺乏相应的数据,你可以主动地去提供这种数据反馈机制。比如说开发一个埋点平台、数据监控平台。尽可能地让业务有数据可看,能够数据驱动,而不是像无头苍蝇一样盲目尝试。
如果无法做一个这么大的系统,那可以先从力所能及的做起,比如说战略上重视数据;做好数据埋点;思考做的功能,目前有哪些数据是核心的,这些数据有没有上报,不同版本的数据是升还是降等。
好,这是第一个阶段,技术对业务价值就是帮助业务快速确定模式。第二个阶段就是业务快速扩大规模时,技术的核心价值是什么呢?
业务从 1 到 100 时
业务正在快速扩大规模时,需要把当前跑通的业务模式复制到更多的地方,同时能够服务更多的用户。这个阶段,技术能够提供的价值主要是两点。
快速迭代(这一点其实无论什么阶段)
提升质量(用户规模日活上亿和日活一万,需要面对的挑战差异也是这个数量级)
第一点:快速迭代
虽然快速迭代是业务各个阶段都需要做到,但和从 0 到 1 相比,从 1 到 100 的阶段会有更多的挑战,除了个人速度,更要关注团队的速度。
团队的速度如何提升?可以参考后端的单体到微服务、前端的单仓到多仓的演变过程及原因。
这个阶段主要有这几点问题:
多人协作代码冲突
发布速度慢
出问题影响大,不好定位
具体到安卓项目,几百人开发和三两个人开发的,复杂度也是几百倍。我们可以做的是:
下沉基础组件,定义组件规范,收敛核心流程
拆分业务模块,设计业务模板,单独维护迭代
探索适合业务的新方式:跨端(RN Flutter KotlinMultiplatform)、动态化、多端逻辑一致(C/C++ Rust)
第二点:提升质量
和日活几万的项目相比,日活千万甚至上亿的产品,需要应对的质量问题更加显著。在这个阶段,我们不仅要满足于实现功能,还要能够写的好,更要能够了解底层原理,才能应对这样大的业务量。
有了大规模的用户后,你会遇到很多奇怪的问题,不能疲于每天去解决一样重复的问题,那你就需要从这些问题中找到一些共通的点,然后提炼出来,输出工具、解决方案甚至平台。
这就需要你从问题中磨练本领,站在更高的层面思考自己该具体的能力、思路和工具。
在解决问题的时候,除了当下这个问题,更需要做的是把这个问题解构、归类,抽象出不同问题的相似和差异,得出问题分析流程图。
同样是分析内存泄漏,有的人可能只知道使用 Leakcanary,但你还可以思考的更深入,比如:
先定义问题。什么是泄露?
泄露是申请了没有释放或者创建了没有回收
内存泄露怎么分析?
找到创建和销毁的点
在创建的时候保存记录,销毁的时候删除这个记录,最终剩下来的就是泄露的
有了基础的逻辑,就可以把它套用到各种问题上:
Native 内存泄漏:在 Native 内存分配和释放 API,做记录
图片使用不当:在图片创建、释放的 API 里做记录
线程过多:在线程创建、释放的 API 里做记录
在遇到一个新问题时,发现和之前解决过的有点像,但又不知道哪里像。怎么办?回头去思考新旧的两个问题,它们的本质是什么?有什么相似的分析思路?
这个思考训练的目的,就是提升举一反三的能力。大规模应用可能各种问题,需要你一方面提升技术,另一方面分析问题的思路和能力上也要提升,不能看着一个问题就是一个问题,要做到看到一个问题,想到一类问题。
展望(后面的规划)
技术上达到一专多能,软实力上持续提升。
硬实力
专业
如果你是安卓开发,最好在某个有细分领域很擅长,比如音视频、跨端、动态化、性能优化。
我目前主要是做优化,后面需要继续补充的知识:
Linux 内核原理
Android 虚拟机原理
项目从开发、编译、发布、数据分析各个流程的效率提升方式
多能
前面提到职业发展的第四个阶段:
不限于该方向,能从产品指标方面出发,提供全方位的技术支持
我希望可以具备独立完成一个系统从前到后的能力。
目前已有的经验:
使用 TypeScript + React + Electron 开发桌面端软件
使用 SpringMVC 开发简单的内部系统
后面需要加强的点:
熟练掌握前端的 js、打包、优化等知识
后端技术达到中级
还有这些点需要长期关注:
Flutter 更新频繁,有一些尝试效果还不错,一套代码多端运行,节省开发成本
掌握 DevOps 理念及实践
最终目的:
具备独立完成一个有价值的系统的能力
具备对研发整个流程的完善、优化能力
软实力
除了技术规划,我也有很多软实力需要继续提升,今年主要想提升的就是同频对话的能力。
什么是同频对话?
同频对话就是根据听众的角色和他的思考角度去转换你的表达内容。
比如说我们在和领导汇报的时候,你要去讲你做的一个系统,你就要从他角度去表达。他可能关注的是整体流程、系统的难点、瓶颈在哪里,带来的收益是什么。那你就不能只讲某个模块的细节,而要从更高的层面去思考和表达。
为什么要提升呢?
随着工作年限的增加,市场对我们的要求是越来越高的,除了写代码,对表达能力的要求也是越来越高的。
一开始刚入行,你就是做一个执行者,只要多动耳朵、眼睛、手,实现别人要求你做的功能。
后来你的能力逐渐提升以后,有机会设计一个模块的时候,你就需要多动脑力去思考,去复设计这个系统的输入输出、内部数据流转等。
再往后走的话,你可能会有一些资源,那就需要能把你的想法完整地表达出来,让别人帮你去贯彻落地。这其实是一种比较难得的能力。我今年计划通过多分享、多与不同的人交流等方式,提升自己的这种能力,争取做到满意的程度。
结束语
好了,这篇文章就到这里了,这就是我这六年的技术回顾和展望,感谢你的阅读❤️。
人生的多重境界:看山是山、看水是水;看山不是山、看水不是水;看山还是山、看水还是水。
我想,我对软件开发,还没有达到第三层,相信用不了多久,就会有不同的观点冒出来。
但,怕什么真理无穷,进一寸有一寸的欢喜!
最后,欢迎学编程的朋友们加入鱼皮的 编程知识星球 ,和上万名学编程的同学共享知识、交流进步,学习原创项目并享有答疑指导服务。
不得不说,现在我们编程导航的内容越来越多元、入驻的嘉宾阵容也越来越强大啦,星球的同学可以随时微信扫码向大佬提问和交流。
往期推荐
我的学习小圈子
腾讯面试体验倍儿好
发现了几个贼有意思的开源项目!
写了7年代码,第一次见这么狗血的小Bug!
代码开源了!